热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

子树|也就是_认识堆和堆排序

篇首语:本文由编程笔记#小编为大家整理,主要介绍了认识堆和堆排序相关的知识,希望对你有一定的参考价值。10、堆

篇首语:本文由编程笔记#小编为大家整理,主要介绍了认识堆和堆排序相关的知识,希望对你有一定的参考价值。



10、堆


10.1、完全二叉树


10.2、大跟堆

在一个完全二叉树里,每一颗子树的最大值就是头结点的值,满足这个条件就是大跟堆。


10.3、小跟堆

在一个完全二叉树中,每一颗子树的最小值就是他的头结点,满足这个条件就是小跟堆。

怎么让一个完全二叉树变成大跟堆呢?

一开始heapsize是为0的,然后5进来的时候,就放到heapsize为0的位置,然后heapsize变为1了,再进来一个数3的时候,将其放到heapsize为1的位置,然后heapsieze变为2;在进来6的时候,将其放到heapsize为2的位置,heapsize变为3;这时候根据父结点的寻找公式来确定子节点的父结点是啥,所以6可以确定他的父结点是5,这时候就要比较父结点跟子节点,子节点要是比父结点大,就得交换两者位置,如果小的话就不用交换位置,继续处理进来的另一个数。通过父结点的比较可以每次进来一个数都能将其调整为大跟堆的形式。

要将大跟堆中的最大值拿掉,怎么让原本的大跟堆还保持大跟堆的状态。

大跟堆的头结点跟最后一个结点的值交换,然后heapsize减小1;heapsize减一之后就以为这之前的头结点也就是换到最后一个结点的值是不存在大跟堆了,因为heapsize减一后如果还要最后一个结点就是下标越界了。

调换之后可能之前的大跟堆已经不再是大跟堆的结构了,所以需要再次调整为大跟堆,怎么调整呢?

从头结点开始,找他的子节点中的最大值,然后最大值跟父结点交换。

问题:如果现在要修改大跟堆中的i位置的某个值为其他的值,那么怎么保证这个完全二叉树还是大跟堆呢?

首先看他修改后的值跟之前的值比较,如果比之前的大,那么就跟上面的进行一个比较,也就是headfy操作。如果比之前的小,就跟下面的进行比较。

堆其实就是只有两个操作,一个是heapsize操作一个是headfy操作。

package 左神算法.;
public class Heap
public static void main(String[] args)
int[] arr = 7, 3, 6, 5, 8;
int index = 4;
int heapSize = 0;
heapInsert(arr, index);
heapify(arr, index, heapSize);
for (int i &#61; 0; i < arr.length; i&#43;&#43;)
System.out.print(arr[i] &#43; " ");


//某个数现在处在index位置&#xff0c;往上继续移动
public static void heapInsert(int[] arr, int index)
while (arr[index] > arr[(index - 1) / 2])
swap(arr, index, (index - 1) / 2);
index &#61; (index - 1) / 2;


//某个数在index位置&#xff0c;能否往下移动
public static void heapify(int[] arr, int index, int heapSize)
int left &#61; index * 2 &#43; 1;//左孩子的下标
while (left < heapSize) //下方还有孩子的时候
// 两个孩子中&#xff0c;谁的值大&#xff0c;把下标给largest
int largest &#61; left &#43; 1 < heapSize && arr[left &#43; 1] > arr[left] ? left &#43; 1 : left;
// 父和孩子之间&#xff0c;谁的值大&#xff0c;把下标给largest
largest &#61; arr[largest] > arr[index] ? largest : index;
if (largest &#61;&#61; index)
break;

swap(arr, largest, index);
index &#61; largest;
left &#61; index * 2 &#43; 1;


public static void swap(int[] arr, int i, int j)
int temp &#61; arr[i];
arr[i] &#61; arr[j];
arr[j] &#61; temp;


/*
8 7 6 5 3
*/

时间复杂度&#xff1a;O(logN)


11、堆排序

时间复杂度&#xff1a;O(NlogN)

如果是给定了所有的元素在堆里面&#xff0c;然后调整成大跟堆&#xff0c;就可以先调整下面的然后继续往上。结果时间复杂度可以计算如下&#xff1a;完全二叉树中的叶子结点是N/2;


11.1、堆排序扩展题目

假设k&#61;6的时候&#xff0c;数组中的0-6中的7个元素加入到小跟堆中&#xff0c;因为k&#61;6&#xff0c;移动距离不能超过6&#xff0c;所以将0-6位置的元素从小跟堆弹出&#xff0c;然后再加入7后面的元素。最后数组中的元素都会从小跟堆弹出到一个数组中

时间复杂度O(N*logK)


推荐阅读
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Java自带的观察者模式及实现方法详解
    本文介绍了Java自带的观察者模式,包括Observer和Observable对象的定义和使用方法。通过添加观察者和设置内部标志位,当被观察者中的事件发生变化时,通知观察者对象并执行相应的操作。实现观察者模式非常简单,只需继承Observable类和实现Observer接口即可。详情请参考Java官方api文档。 ... [详细]
  • 数组的排序:数组本身有Arrays类中的sort()方法,这里写几种常见的排序方法。(1)冒泡排序法publicstaticvoidmain(String[]args ... [详细]
  • 面向对象之3:封装的总结及实现方法
    本文总结了面向对象中封装的概念和好处,以及在Java中如何实现封装。封装是将过程和数据用一个外壳隐藏起来,只能通过提供的接口进行访问。适当的封装可以提高程序的理解性和维护性,增强程序的安全性。在Java中,封装可以通过将属性私有化并使用权限修饰符来实现,同时可以通过方法来访问属性并加入限制条件。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 从零学Java(10)之方法详解,喷打野你真的没我6!
    本文介绍了从零学Java系列中的第10篇文章,详解了Java中的方法。同时讨论了打野过程中喷打野的影响,以及金色打野刀对经济的增加和线上队友经济的影响。指出喷打野会导致线上经济的消减和影响队伍的团结。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • Go语言实现堆排序的详细教程
    本文主要介绍了Go语言实现堆排序的详细教程,包括大根堆的定义和完全二叉树的概念。通过图解和算法描述,详细介绍了堆排序的实现过程。堆排序是一种效率很高的排序算法,时间复杂度为O(nlgn)。阅读本文大约需要15分钟。 ... [详细]
  • (三)多表代码生成的实现方法
    本文介绍了一种实现多表代码生成的方法,使用了java代码和org.jeecg框架中的相关类和接口。通过设置主表配置,可以生成父子表的数据模型。 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • JavaScript设计模式之策略模式(Strategy Pattern)的优势及应用
    本文介绍了JavaScript设计模式之策略模式(Strategy Pattern)的定义和优势,策略模式可以避免代码中的多重判断条件,体现了开放-封闭原则。同时,策略模式的应用可以使系统的算法重复利用,避免复制粘贴。然而,策略模式也会增加策略类的数量,违反最少知识原则,需要了解各种策略类才能更好地应用于业务中。本文还以员工年终奖的计算为例,说明了策略模式的应用场景和实现方式。 ... [详细]
  • 多维数组的使用
    本文介绍了多维数组的概念和使用方法,以及二维数组的特点和操作方式。同时还介绍了如何获取数组的长度。 ... [详细]
author-avatar
eggplant
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有